package logger

import (
	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
)

type LogOption struct {
	LogPath    string `yaml:"logPath" json:"logPath"`
	AppName    string `yaml:"appName" json:"appName"`
	Debug      bool   `yaml:"debug" json:"debug"`
	Level      int8   `yaml:"level" json:"level"`
	MaxSize    int    `yaml:"maxSize" json:"maxSize"`
	MaxAge     int    `yaml:"maxAge" json:"maxAge"`
	MaxBackups int    `yaml:"maxBackups" json:"maxBackups"`
	Compress   bool   `yaml:"compress" json:"compress"`
}

var ZapLogger *zap.Logger

func Get() *zap.Logger {
	return ZapLogger
}

func InitLogger(logOption *LogOption) {

	if logOption.MaxSize < 1 {
		logOption.MaxSize = 1
	}

	if logOption.MaxAge < 1 {
		logOption.MaxAge = 1
	}

	if logOption.MaxBackups < 1 {
		logOption.MaxBackups = 1
	}

	hook := lumberjack.Logger{
		Filename:   logOption.LogPath,    // 日志文件路径
		MaxSize:    logOption.MaxSize,    // 每个日志文件保存的大小 单位:M
		MaxAge:     logOption.MaxAge,     // 文件最多保存多少天
		MaxBackups: logOption.MaxBackups, // 日志文件最多保存多少个备份
		Compress:   false,                // 是否压缩
	}
	encoderConfig := zapcore.EncoderConfig{
		MessageKey:     "msg",
		LevelKey:       "level",
		TimeKey:        "time",
		NameKey:        "logger",
		CallerKey:      "file",
		StacktraceKey:  "stacktrace",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.LowercaseLevelEncoder,
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder, // 短路径编码器
		EncodeName:     zapcore.FullNameEncoder,
	}
	// 设置日志级别
	atomicLevel := zap.NewAtomicLevel()

	//zapcore.Level(logOption.Level)
	atomicLevel.SetLevel(zapcore.Level(logOption.Level))
	var writes = []zapcore.WriteSyncer{zapcore.AddSync(&hook)}
	// 如果是开发环境，同时在控制台上也输出
	if logOption.Debug {
		writes = append(writes, zapcore.AddSync(os.Stdout))
	}
	warnLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl >= zapcore.WarnLevel
	})
	encoder := zapcore.NewJSONEncoder(encoderConfig)
	core := zapcore.NewTee(
		zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(writes...), atomicLevel),
		zapcore.NewCore(encoder, zapcore.AddSync(&lumberjack.Logger{
			Filename:   logOption.LogPath,
			MaxSize:    logOption.MaxSize,
			MaxBackups: logOption.MaxBackups,
			MaxAge:     logOption.MaxAge,
			Compress:   logOption.Compress,
		}), warnLevel),
	)

	// 开启开发模式，堆栈跟踪
	caller := zap.AddCaller()
	// 开启文件及行号
	development := zap.Development()
	// 设置初始化字段
	field := zap.Fields(zap.String("appName", logOption.AppName))
	// 构造日志
	ZapLogger = zap.New(core, caller, development, field)
	ZapLogger.Info("log 初始化成功")
}
